Skip to content

feat: add admin apis (CM-1235)#4211

Merged
ulemons merged 10 commits into
mainfrom
feat/steward-admin-actions-api
Jun 16, 2026
Merged

feat: add admin apis (CM-1235)#4211
ulemons merged 10 commits into
mainfrom
feat/steward-admin-actions-api

Conversation

@ulemons

@ulemons ulemons commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Summary

Expose four admin-facing endpoints to support stewardship lifecycle management in the OSSPREY Program dashboard. Admins can now open a package for stewardship, assign individual stewards, escalate with a structured resolution path, and update stewardship status — all with audit logging to stewardship_activity.

Changes

  • POST /api/public/v1/stewardships — opens a package for stewardship (upserts status → open); body takes a PURL, normalised before DB lookup
  • PUT /api/public/v1/stewardships/:id/steward — assigns a steward (lead or co_steward) via soft-delete + insert pattern; entire operation is wrapped in a transaction to keep the audit log consistent
  • PUT /api/public/v1/stewardships/:id/escalate — sets status → escalated and records one of 6 resolution paths in stewardship_activity metadata
  • PUT /api/public/v1/stewardships/:id/status — updates stewardship status (assessing, active, needs_attention, blocked, inactive); inactiveReason is required when setting inactive and is preserved on other transitions (not overwritten to null)
  • DAL (stewardships.ts) — added getStewardshipById, openStewardshipByPurl, assignSteward, escalateStewardship, updateStewardshipStatus; exported ESCALATION_RESOLUTION_PATHS, INACTIVE_REASONS, and STEWARDSHIP_UPDATABLE_STATUSES as shared constants
  • Auth0 scope checks commented out with TODO following the same pattern as existing packages endpoints (restore once write:stewardships is provisioned on the Auth0 staging tenant)

Type of change

  • Bug fix
  • New feature
  • Refactor / cleanup
  • Performance improvement
  • Chore / dependency update
  • Documentation

JIRA ticket

ticket


Note

High Risk
Introduces authenticated admin mutations that change stewardship state and steward assignments with scope enforcement temporarily disabled; incorrect transitions or missing authorization could affect program-critical package stewardship data.

Overview
Adds write stewardship admin APIs under /api/v1/stewardships: open by PURL, assign stewards (optional atomic move to assessing), escalate with a resolution path, and update status (with required inactiveReason for inactive). Handlers delegate to new DAL mutations that upsert/update stewardships, manage stewardship_stewards, and append stewardship_activity audit rows.

Read paths now surface real stewardship data instead of v1 placeholders: package list/detail include stewardshipId, stewards, lastActivityAt, resolutionPath, and statusNote (detail loads stewards/activity via getStewardshipSummary). OpenAPI is updated accordingly; steward userId is documented as Auth0 sub.

A migration adds stewardships.resolution_path and status_note. write:stewardships scope checks are commented out (same temporary pattern as packages) until Auth0 staging is provisioned (CM-1235).

Reviewed by Cursor Bugbot for commit 7bf574d. Bugbot is set up for automated code reviews on this repo. Configure here.

@ulemons ulemons self-assigned this Jun 15, 2026
Copilot AI review requested due to automatic review settings June 15, 2026 10:41
@ulemons ulemons added the Feature Created by Linear-GitHub Sync label Jun 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new set of Auth0-protected public v1 API endpoints plus supporting DAL methods to manage OSSPCKGS “stewardship” lifecycle actions (open, assign steward, escalate, update status) while writing audit entries to stewardship_activity.

Changes:

  • Added DAL helpers for stewardship CRUD-ish workflows and exported shared constants for request validation.
  • Added four new /api/public/v1/stewardships/* handlers with Zod validation and wired them into the v1 router.
  • Added routing for the new stewardship endpoints under the existing Auth0 oauth2Middleware.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
services/libs/data-access-layer/src/osspckgs/stewardships.ts Adds DAL APIs for opening, assigning, escalating, and status updates + shared enum constants.
backend/src/api/public/v1/stewardships/openStewardship.ts New POST handler to open a package for stewardship via normalized PURL.
backend/src/api/public/v1/stewardships/assignSteward.ts New PUT handler to soft-delete + insert a steward assignment.
backend/src/api/public/v1/stewardships/escalate.ts New PUT handler to escalate a stewardship with a resolution path.
backend/src/api/public/v1/stewardships/updateStatus.ts New PUT handler to update stewardship status with conditional inactiveReason validation.
backend/src/api/public/v1/stewardships/schemas.ts Adds shared param schema for numeric stewardship id.
backend/src/api/public/v1/stewardships/index.ts Adds stewardships router + rate limiting (scope checks currently commented out).
backend/src/api/public/v1/index.ts Mounts the new /stewardships router under v1 with Auth0 middleware.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts
Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts Outdated
Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts
Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts
Comment thread backend/src/api/public/v1/stewardships/index.ts
@ulemons ulemons force-pushed the feat/steward-admin-actions-api branch from 8af239c to 3f87f89 Compare June 15, 2026 10:51
Copilot AI review requested due to automatic review settings June 15, 2026 11:13
@ulemons ulemons force-pushed the feat/steward-admin-actions-api branch from e1b707e to 03abe99 Compare June 15, 2026 11:29
Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment thread backend/src/api/public/v1/packages/getPackage.ts
Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts
Copilot AI review requested due to automatic review settings June 15, 2026 14:17
Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts Outdated
Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts
Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts
Comment thread backend/src/api/public/v1/stewardships/openapi.yaml
Comment thread backend/src/api/public/v1/stewardships/index.ts
Copilot AI review requested due to automatic review settings June 15, 2026 16:35

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 01f5fee. Configure here.

Comment thread services/libs/data-access-layer/src/osspckgs/stewardships.ts
`,
{ stewardshipId, actorUserId: data.assignedBy, metadata: JSON.stringify({ status: 'assessing' }) },
)
if (updated) finalStewardship = mapStewardshipRow(updated)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moveToAssessing succeeds without status change

Medium Severity

With moveToAssessing true, the status UPDATE only applies when status is unassigned or open. If the stewardship is already past that (e.g. active), the handler still returns 200 with stewards updated but the prior status unchanged, so clients believe an atomic move to assessing occurred when it did not.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 01f5fee. Configure here.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

backend/src/api/public/v1/packages/openapi.yaml:443

  • The field-level description for stewards still says "Null in v1", but GET /packages/detail can now return an array (possibly empty) when a stewardship exists.
            stewards:
              description: Assigned stewards or null. Null in v1.
              oneOf:
                - type: array
                  items:
                    $ref: '#/components/schemas/Steward'
                - type: 'null'

Comment on lines +223 to +232
SET status = 'assessing',
last_status_at = NOW(),
resolution_path = NULL,
status_note = NULL,
updated_at = NOW()
WHERE id = $(stewardshipId)
AND status IN ('unassigned', 'open')
RETURNING id, package_id, status, origin, version, opened_at,
last_status_at, inactive_reason, resolution_path, status_note, created_at, updated_at
),
Comment on lines +385 to +388
SET status = $(status),
last_status_at = NOW(),
inactive_reason = CASE WHEN $(status) = 'inactive' THEN $(inactiveReason) ELSE NULL END,
updated_at = NOW()
Comment on lines +1 to +19
import { Router } from 'express'

import { createRateLimiter } from '@/api/apiRateLimiter'
// TODO: restore once write:stewardships is added to Auth0 staging tenant
// import { requireScopes } from '@/api/public/middlewares/requireScopes'
import { safeWrap } from '@/middlewares/errorMiddleware'

// import { SCOPES } from '@/security/scopes'
import { assignStewardHandler } from './assignSteward'
import { escalateHandler } from './escalate'
import { openStewardship } from './openStewardship'
import { updateStatusHandler } from './updateStatus'

const rateLimiter = createRateLimiter({ max: 60, windowMs: 60 * 1000 })

export function stewardshipsRouter(): Router {
const router = Router()

router.use(rateLimiter)
Comment on lines +88 to +96
inactiveReason:
type:
- string
- 'null'
enum:
- quarterly_cadence_missed
- stepped_down
- no_longer_critical
- 'null'
Comment on lines 425 to 428
stewardship:
type: object
description: Stewardship state. In v1 always unassigned with no stewards or activity.
properties:
ulemons and others added 9 commits June 16, 2026 09:28
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>
Copilot AI review requested due to automatic review settings June 16, 2026 07:28
Signed-off-by: Umberto Sgueglia <usgueglia@contractor.linuxfoundation.org>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Comment on lines +158 to +165
ON CONFLICT (package_id) DO UPDATE
SET status = 'open',
opened_at = NOW(),
last_status_at = NOW(),
inactive_reason = NULL,
resolution_path = NULL,
status_note = NULL,
updated_at = NOW()
return v instanceof Date ? v.toISOString() : String(v)
}

function mapStewardStewardRow(row: Record<string, unknown>): StewardshipStewardRecord {
Comment on lines +21 to +25
router.post(
'/',
// TODO: restore once write:stewardships is added to Auth0 staging tenant
// requireScopes([SCOPES.WRITE_STEWARDSHIPS]),
safeWrap(openStewardship),
@ulemons ulemons merged commit 84a58c7 into main Jun 16, 2026
15 checks passed
@ulemons ulemons deleted the feat/steward-admin-actions-api branch June 16, 2026 07:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature Created by Linear-GitHub Sync

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants